import math
from datetime import datetime
from odoo import fields, models, api, SUPERUSER_ID, _
from odoo.exceptions import UserError
from odoo.tools import float_compare


class ProductionMaterialDemandWizard(models.Model):
    _name = 's.production.material.demand.wizard'
    _description = 'Production Material Demand Wizard'

    location_id = fields.Many2one('stock.location', required=True)
    location_dest_id = fields.Many2one('stock.location', required=True)
    picking_type_id = fields.Many2one('stock.picking.type', required=True)
    work_station_id = fields.Many2one('work.station', string='Use Station', required=True)
    line_ids = fields.One2many('s.production.material.demand.line.wizard', 'order_id')

    def default_get(self, fields_list):
        result = super().default_get(fields_list)
        picking_type_id = self.env['stock.picking.type'].search([('barcode', '=', 'WTT-INTERNAL')], limit=1)
        location_dest_id = self.env['stock.location'].search([('barcode', '=', 'WH-PREPRODUCTION')], limit=1)
        if not picking_type_id:
            warehouse_id = self.env['stock.warehouse'].search([('company_id', '=', self.env.user.company_id.id)], limit=1)
            picking_type_id = warehouse_id.pbm_type_id
        order_ids = self.env['s.production.material.demand'].browse(self._context.get('active_ids'))
        line_vals = []
        for order in order_ids:
            # 库存数量 转采购单位
            product = order.product_id
            if product.uom_id == product.uom_po_id:
                ratio_str = '1:1'
                ratio = 1
                qty = min(product.s_actual_quantity, order.difference)
            else:
                uom_po_qty = math.floor(product.uom_id._compute_quantity(product.s_actual_quantity, product.uom_po_id, round=False))
                need_uom_po_qty = math.ceil(product.uom_id._compute_quantity(order.difference, product.uom_po_id, round=False))
                need_qty = min(need_uom_po_qty, uom_po_qty)
                qty = product.uom_po_id._compute_quantity(need_qty, product.uom_id, round=False)
                ratio_qty = qty
                ratio_str = f'{need_qty}:{qty}'
                if need_qty == 0:
                    need_qty = 1
                ratio = ratio_qty / need_qty

            line_vals.append((0, 0, {
                'product_id': order.product_id.id,
                'ratio_str': ratio_str,
                'ratio': ratio,
                'qty': qty,
            }))
        result.update({
            'picking_type_id': picking_type_id.id,
            'location_id': picking_type_id.default_location_src_id.id,
            'location_dest_id': location_dest_id.id,
            'line_ids': line_vals
        })
        return result

    def action_confirm(self):
        if not self.line_ids:
            raise UserError('Please add transfer details!')
        if self.line_ids.filtered(lambda x: x.qty <= 0):
            raise UserError('The transfer quantity cannot be less than 0!')
        vals = {
            'company_id': self.env.user.company_id.id,
            'location_id': self.location_id.id,
            'location_dest_id': self.location_dest_id.id,
            'move_type': 'direct',
            'picking_type_id': self.picking_type_id.id,
            'user_id': self.env.user.id,
            'work_station_id': self.work_station_id.id,
            'apply_uid': self.env.user.id
        }
        move_vals_list = []
        for line in self.line_ids:
            if float_compare(line.product_id.s_actual_quantity, line.qty, precision_rounding=line.product_id.uom_id.rounding) == -1:
                raise UserError(_('product %s, The transfer quantity is greater than the inventory quantity', line.product_id.display_name))
            move_vals_list.append((0, 0, {
                'company_id': self.env.user.company_id.id,
                'date': datetime.now(),
                'location_id': self.location_id.id,
                'location_dest_id': self.location_dest_id.id,
                'product_id': line.product_id.id,
                'name': line.product_id.display_name,
                'procure_method': 'make_to_stock',
                'product_uom': line.product_id.uom_id.id,
                'product_before_rounding_qty': line.qty,
                'product_uom_qty': line.qty
            }))
        vals['move_ids'] = move_vals_list
        picking_id = self.env['stock.picking'].with_user(SUPERUSER_ID).create(vals)
        picking_id.with_user(SUPERUSER_ID).action_confirm()
        return {
            'name': _('Production Material Picking'),
            'type': 'ir.actions.act_window',
            'res_model': 'stock.picking',
            'view_mode': 'tree,form',
            'target': 'current',
            'views': [[False, 'tree'], [False, 'form']],
            'context': {'create': False},
            'domain': [('id', 'in', picking_id.ids)],
        }


class ProductionMaterialDemandLineWizard(models.Model):
    _name = 's.production.material.demand.line.wizard'
    _description = 'Production Material Demand Line Wizard'

    order_id = fields.Many2one('s.production.material.demand.wizard')
    product_id = fields.Many2one('product.product', string='Product')
    default_code = fields.Char(related='product_id.default_code', string='Code')

    stock_qty = fields.Float('Stock Quantity', digits='Product Unit of Measure', related='product_id.s_actual_quantity')
    qty = fields.Float('Quantity', digits='Product Unit of Measure')
    uom_id = fields.Many2one('uom.uom', string='Uom', related='product_id.uom_id')
    ratio_str = fields.Char(string='Ratio')
    ratio = fields.Float(string='f ratio', digits=(12, 4))

    @api.onchange('qty')
    def onchange_qty(self):
        if self.qty == 0 or self.ratio == 0:
            return
        if not (self.qty / self.ratio).is_integer():
            return {
                'warning': {
                    'title': _("Warning"),
                    'message': _('The quantity converted to purchasing unit is not an integer, please modify the quantity')
                }}
